目前畫面上的地區是固定的,但我們這個 App 是要顯示目前所在地區的天氣,所以這篇文章會示範如何取得目前所在地區的資料,並且顯示在畫面上。
目前我們已經透過 Expo Location 來取得目前所在地區的經緯度,不過只有經緯度還不夠,我們還需要透過經緯度來取得地區名稱,這裡會使用到 Geocoding API 來反向取得地區名稱。
詳細的申請流程可以參考 這篇我寫的文章。
取得 Geocoding API 的 URL 以及 API Key 後,我們要把它們放到 .env
檔案中方便使用:
EXPO_PUBLIC_GEOCODING_API_KEY=輸入你的 API Key
EXPO_PUBLIC_GEOCODING_API_URL=https://maps.googleapis.com/maps/api/geocode/json?
因為前面已經用 Zustand 做好狀態管理,所以現在要新增方法非常方便,只要在 store/index.ts
新增有關 city 的狀態還有 API 即可:
interface AddressComponent {
long_name: string;
short_name: string;
types: string[];
}
interface LocationResult {
address_components: AddressComponent[];
}
interface Store {
location: Location.LocationObject | null
errorMsg: string | null
currentWeather: CurrentWeatherInfo | null
city: string | null
setCity: (city: string | null) => void
setLocation: (location: Location.LocationObject | null) => void
setErrorMsg: (msg: string | null) => void
setCurrentWeather: (weather: CurrentWeatherInfo | null) => void
fetchWeatherData: () => Promise<void>
fetchLocation: () => Promise<void>
}
const useStore = create<Store>((set) => ({
location: null,
errorMsg: null,
currentWeather: null,
city: null,
setCity: (city) => set({ city }),
setLocation: (location) => set({ location }),
// 省略其他程式碼
fetchLocation: async () => {
const { location } = useStore.getState()
if (location && location.coords) {
const { latitude, longitude } = location.coords
const apiUrl = process.env.EXPO_PUBLIC_GEOCODING_API_URL
const apiKey = process.env.EXPO_PUBLIC_GEOCODING_API_KEY
try {
const res = await fetch(
`${apiUrl}latlng=${latitude},${longitude}&key=${apiKey}&language=en`
)
const json = await res.json()
const cityComponent = json.results
.flatMap((result: LocationResult) => result.address_components)
.find((component: AddressComponent) => component.types.includes('locality'))
if (cityComponent) {
useStore.getState().setCity(cityComponent.long_name)
} else {
console.error('City name not found')
}
} catch (err) {
console.log(err)
}
}
}
}))
接下來在 App.tsx
中呼叫 API:
export default function App() {
const { location, errorMsg, setLocation, setErrorMsg, fetchWeatherData, fetchLocation } = useStore()
// 省略其他程式碼
useEffect(() => {
if (location) {
fetchWeatherData()
fetchLocation()
}
}, [location])
return (
<SafeAreaView className='flex-1 bg-blue-500'>
// 省略其他程式碼
</SafeAreaView>
)
}
當 location
有值時,就會呼叫 fetchLocation
方法,這樣就可以取得目前所在地區的名稱了。
最後在 HeadInfo.tsx
中顯示目前地區:
import { View, Text } from 'react-native'
import useStore from '../store'
const HeaderInfo = () => {
const { city } = useStore()
return (
<View className='items-center p-6 space-y-4 w-500'>
<Text className='text-2xl font-semibold text-white'>{city}</Text>
<Text className='text-sm text-gray-200'>Monday, 12 September</Text>
</View>
)
}
可以測試一下 Custom Location,觀察目前地區是否有變化。
這篇文章展示了如何將 Expo Location 取得的經緯度,透過 Geocoding API 的應用來取得目前所在地區的名稱,明天來處理現在時間的顯示,明天見👋!